package net.cloudsun.tree.binary;

import net.cloudsun.tree.Node;
import net.cloudsun.tree.Tree;

import java.util.function.Consumer;
import java.util.function.Predicate;

/**
 * @author Ryan
 * @since
 */
public abstract class BinaryTree<T> implements Tree<T> {

    protected BinaryNode<T> root;

    public BinaryTree() {
    }

    public BinaryTree(BinaryNode<T> root) {
        this.root = root;
    }

    public BinaryNode<T> getRoot() {
        return root;
    }

    /**
     * @param root
     */
    protected void setRoot(BinaryNode<T> root) {
        this.root = root;
    }

    /**
     * 泛型真是搞不懂啊，很容易写错
     * @param root
     * @param <S>
     */
    protected <S> void setRoot(S root) {
        this.root = (BinaryNode<T>) root;
    }

    public void add(T t) {
        if (t == null) {
            throw new NullPointerException();
        }
        final BinaryNode<T> newNode = createNode(t);
        if (root == null) {
            root = newNode;
            return;
        }

        root.add(newNode);
    }

    protected abstract BinaryNode<T> createNode(T t);

    @Override
    public BinaryNode<T> findNode(T t) {
        if (t == null) {
            throw new NullPointerException();
        }
        final BinaryNode<T>[] binaryNodes = new BinaryNode[1];
        bfs(node -> {
            if (node.getValue().equals(t)) {
                binaryNodes[0] = (BinaryNode<T>) node;
                return false;
            }
            return true;
        });
        return binaryNodes[0];
    }

    /**
     * 宽度搜索
     *
     * @param visitor
     */
    public void bfs(Predicate<Node<T>> visitor) {
        if (root == null) {
            return;
        }
        root.bfs(visitor);
    }

    /**
     * 深度搜索
     *
     * @param visitor
     */
    public void dfs(Predicate<Node<T>> visitor) {
        if (root == null) {
            return;
        }
        root.dfs(visitor);
    }

    public void forEach(Consumer<Node<T>> visitor) {
       if (root != null) {
           root.forEach(visitor);
       }
    }

    /**
     * @return 构建一个字符串
     */
    public String toTreeString() {
        if (root == null) {
            return "";
        }
        return root.toTreeString();
    }

}


